﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.VisualStudio.TextTemplating.VSHost;
using System.IO;
using System.Runtime.InteropServices;
using RBTools.CodeGenerator.CodeDomGenerator.Hosts;
using Microsoft.VisualStudio.TextTemplating;
using System.CodeDom.Compiler;

namespace RBTools.CodeGenerator.CodeDomGenerator
{
    [GuidAttribute("01607FE2-88A6-40D6-9F2E-D7690A12E82E")]
    [Serializable]
    public  class ExtedmxCodeGenerator : BaseCodeGeneratorWithSite
    {
        private const string BaseTemplatePath = @"C:\CodeGenerators\Templates\EntityFramework";

        #region Ctors

        public ExtedmxCodeGenerator()
        {
            TemplateFileFullName = Path.Combine(BaseTemplatePath, "CSharpEntityModel.tt");
            ExtTemplateFileFullName = Path.Combine(BaseTemplatePath, "CSharpEntityModelExt.tt");
        }

        #endregion

        #region Properties

        public string ExtTemplateFileFullName
        {
            get;
            set;
        }

        public string TemplateFileFullName
        {
            get;
            set;
        }
         

        #endregion

        #region Generate Code

        protected string GenerateCode(EnvDTE.ProjectItem projectItem)
        {
            string NamespaceSuggestion = GetNamespaceSuggestion(projectItem);
            string edmxDataFilename = GetEdmxFileName(projectItem);

            ExtedmxTextTemplatingEngineHost host = new ExtedmxTextTemplatingEngineHost();
            Engine engine = new Engine();
            host.CurrentProjectItem = projectItem;
            host.TemplateFile = TemplateFileFullName;
            host.NamespaceSuggestion = NamespaceSuggestion;

            //Read the text template
            string input = File.ReadAllText(TemplateFileFullName);

            input = input.Replace("$extedmxInputFile$", projectItem.FileNames[1]);
            input = input.Replace("$edmxInputFile$", edmxDataFilename);
            input = input.Replace("$namespace$", NamespaceSuggestion); 
           

            //return NamespaceSuggestion +"  "+ edmxDataFilename;
            //Transform the text template

            string output = engine.ProcessTemplate(input, host);
            if (host.Errors != null && host.Errors.Count > 0)
            {
                output += "//" + edmxDataFilename + Environment.NewLine;
                output += "//" + NamespaceSuggestion + Environment.NewLine;

                foreach (CompilerError error in host.Errors)
                {
                    output += Environment.NewLine + error.ErrorText;
                }
            } 

            return output;
        }

        protected string GenerateExtCode(EnvDTE.ProjectItem projectItem)
        {
            string NamespaceSuggestion = GetNamespaceSuggestion(projectItem);
            string edmxDataFilename = GetEdmxFileName(projectItem);

            ExtedmxTextTemplatingEngineHost host = new ExtedmxTextTemplatingEngineHost();
            Engine engine = new Engine();
            host.TemplateFile = ExtTemplateFileFullName;
            host.NamespaceSuggestion = NamespaceSuggestion;

            //Read the text template
            string input = File.ReadAllText(TemplateFileFullName);

            input = input.Replace("$edmxInputFile$", edmxDataFilename);
            input = input.Replace("$namespace$", NamespaceSuggestion);

            //return NamespaceSuggestion +"  "+ edmxDataFilename;
            //Transform the text template

            string output = engine.ProcessTemplate(input, host);
            if (host.Errors != null && host.Errors.Count>0)
            {
                output += "//" + edmxDataFilename + Environment.NewLine;
                output += "//" + NamespaceSuggestion + Environment.NewLine;

                foreach (CompilerError error in host.Errors)
                {
                    output += Environment.NewLine + error.ErrorText;
                }
            }
            output += "//Success";
            return output;
        }
        #endregion

        #region Implement BaseCodeGeneratorWithSite abstract methods

        protected override byte[] GenerateCode(string inputFileName, string inputFileContent)
        {
            EnvDTE.ProjectItem projectItem = GetService(typeof(EnvDTE.ProjectItem)) as EnvDTE.ProjectItem;
            //try
            //{
            //    string templateFileName = Path.ChangeExtension(inputFileName, ".designer.cs");
                
            //    EnvDTE.Document templateDocument = this.Dte.Documents.Cast<EnvDTE.Document>().SingleOrDefault(d => d.FullName == templateFileName);
                 

            //    if (templateDocument == null && projectItem != null)
            //    { 
            //        EnvDTE.ProjectItem extProjectItem = projectItem.ProjectItems.AddFromTemplate(Path.ChangeExtension(ExtTemplateFileFullName,".designer.cs"), Path.GetFileNameWithoutExtension(inputFileName)+".designer.cs");
            //        File.WriteAllText(extProjectItem.FileNames[1],GenerateExtCode(extProjectItem));
            //    }
            //}
            //catch (Exception error)
            //{ }

            string templateFileContent = String.Empty;
            Encoding templateEncoding = Encoding.UTF8;
            // Otherwise, create a new, empty one           

            templateFileContent = GenerateCode(projectItem);

            //templateFileContent = NamespaceSuggestion;

            return templateEncoding.GetBytes(templateFileContent); 
        }

        public override string GetDefaultExtension()
        {
            return ".cs";
        }

        #endregion

        #region Other Methods

        private string GetEdmxFileName(EnvDTE.ProjectItem projectItem)
        {
            string fileName = string.Empty;

            string templateFileName = Path.ChangeExtension(projectItem.FileNames[1], GetEdmxFileExtension());

            return templateFileName;
        }

        private string GetNamespaceSuggestion(EnvDTE.ProjectItem projectItem)
        {
            return projectItem.ContainingProject.Name + "." + Path.GetFileNameWithoutExtension(projectItem.Name);
        }

        private string GetEdmxFileExtension()
        {
            return ".edmx";
        }
        #endregion
    }
}
